﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using Dataglot;
using IrishSettings.Commands;

namespace IrishSettings.TableControllers
{
    public class SchemaSettingsController : TableController<GenericSettingSchema>
    {
        public SchemaSettingsController(DataFactory factory, DbConnection connection, DbTransaction transaction)
            : base(factory, connection, transaction)
        {
            if(connection==null)
                throw new ArgumentException("connection parameter required, can't be null");
            tableName = "{$ns}_settings_schema";

            sharedConnection = connection;
            columns = new Dictionary<string,DbType>
                          { 
                              {"id",DbType.Int32},
                              {"application_id",DbType.Int32},
                              {"name",DbType.String},
                              {"default_serialized_value",DbType.String},
                              {"scope",DbType.String},
                              {"value_type",DbType.String},
                              {"is_user",DbType.Boolean},
                              {"is_anonymous",DbType.Boolean}
                          };
        }

        public override GenericSettingSchema Select(long id)
        {
            return ProcessSelect(id);
        }

        public override List<GenericSettingSchema> SelectList(int from, int to)
        {
            return ProcessSelectList(from, to);
        }

        public override GenericSettingSchema Insert(GenericSettingSchema setting)
        {
            return ProcessInsert(setting);
        }

        public override GenericSettingSchema Update(GenericSettingSchema setting)
        {
            return ProcessUpdate(setting);   
        }

        public override void Delete(long id)
        {
            ProcessDelete(id);
        }

        public override bool Exists(long id)
        {
            return ProcessExists(id);
        }

        public bool ExistByName(string name, long applicationId)
        {
            using (SelectSchemaByName command = new SelectSchemaByName(factory, sharedConnection, sharedTransaction))
            {
                using (DbDataReader reader = command.Select(name, applicationId))
                {
                    if (reader.HasRows)
                        return true;
                    else
                    {
                        return false;
                    }
                }
            }

        }

        public GenericSettingSchema SelectByName(string name, long applicationId)
        {
            using (SelectSchemaByName command = new SelectSchemaByName(factory, sharedConnection, sharedTransaction))
            {
                long id;
                using (DbDataReader reader = command.Select(name, applicationId))
                {
                    reader.Read();
                    id = Convert.ToInt64(reader.GetValue(0));
                }
                return ProcessSelect(id);
                
            }
        }

        public List<long> SelectListOfIdsByVersion(long applicationId, Version version)
        {
            if (applicationId == 0)
                throw new ArgumentException("Missing app Id", "applicationId");

            if (version == null)
                throw new ArgumentException("Missing version", "version");

            List<long> ids = new List<long>();
            using (SelectSchemaByApplicationNameAndVersion command = new SelectSchemaByApplicationNameAndVersion(factory, sharedConnection, sharedTransaction))
            {
                using (DbDataReader reader = command.SelectRows(applicationId, version))
                {
                    while (reader.Read())
                    {
                        ids.Add(Convert.ToInt64(reader.GetValue(0)));

                    }
                }
            }
            return ids;
        }

        public SettingsSchema SelectListByVersion(string applicationName, Version version)
        {
            SettingsApplication appObject;
            using (ApplicationAndVersionController versionController = new ApplicationAndVersionController(factory,sharedConnection,sharedTransaction))
            {
               appObject =  versionController.SelectByApplicationName(applicationName, version);
            }

            SettingsSchema list = new SettingsSchema();
            using (SelectSchemaByApplicationNameAndVersion command = new SelectSchemaByApplicationNameAndVersion(factory, sharedConnection, sharedTransaction))
            {
                List<long> ids = SelectListOfIdsByVersion(appObject.Id, appObject.VersionObject);

                foreach (long id in ids)
                {
                    GenericSettingSchema item = ProcessSelect(id);
                    if(item.Id==0)
                        throw new InvalidOperationException("Missing schema Id");
                    list.ValidateAndAdd(item.Name, item);
                    //list.Add();
                }
            }
            return list;
        }

        /// <summary>
        /// Creates a new schema, but doesn't upgrade values.
        /// </summary>
        public void CopySchemaForNewVersion(SettingsApplication application, Version oldVersion, Version newVersion)
        {
            SettingsSchema schema = SelectListByVersion(application.Application, oldVersion);
            foreach (KeyValuePair<string, GenericSettingSchema> keyValuePair in schema)
            {
                GenericSettingSchema item = keyValuePair.Value;
                item.ApplicationId = application.Id;
                Insert(item);
            }
        }
    }
}
